﻿#region Copyright and license information
// Copyright 2001-2009 Stephen Colebourne
// Copyright 2009-2011 Jon Skeet
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;

namespace NodaTime.Xml
{
   /// <summary>
   ///   The Noda Time Schema (XSD) specification.
   /// </summary>
   /// <threadsafety>
   ///   All public static members of this type are thread safe.
   /// </threadsafety>
   /// <remarks>
   ///   <b>NodaTimeSchema</b> provides .Net accessible definitions for the <see cref="Schema">Noda Time Schema (XSD)</see>.  All types are in
   ///   <see cref="Namespace">this namespace</see>.
   /// </remarks>
   public static class NodaTimeSchema
   {
      /// <summary>
       ///   The XML namespace for Noda. Defined as "urn:noda-time".
      /// </summary>
      public const string Namespace = "urn:noda-time"; 

      /// <summary>
      ///   The XML type name for an <see cref="Instant"/>.
      /// </summary>
      /// <value>
      ///   A <see cref="XmlQualifiedName"/> of "<see cref="Namespace"/>:instant".
      /// </value>
      public static readonly XmlQualifiedName InstantTypeName = new XmlQualifiedName("instant", Namespace);

      /// <summary>
      ///   The XML type name for an <see cref="Interval"/>.
      /// </summary>
      public static readonly XmlQualifiedName IntervalTypeName = new XmlQualifiedName("interval", Namespace);

       /// <summary>
      ///   The XML type name for a <see cref="LocalDate"/>.
      /// </summary>
      public static readonly XmlQualifiedName LocalDateTypeName = new XmlQualifiedName("localDate", Namespace);

      /// <summary>
      ///   The XML type name for a <see cref="LocalDateTime"/>.
      /// </summary>
      public static readonly XmlQualifiedName LocalDateTimeTypeName = new XmlQualifiedName("localDateTime", Namespace);

      /// <summary>
      ///   The XML type name for a <see cref="LocalTime"/>.
      /// </summary>
      public static readonly XmlQualifiedName LocalTimeTypeName = new XmlQualifiedName("localTime", Namespace);

      /// <summary>
      ///   The XML type name for a <see cref="Duration"/>.
      /// </summary>
      public static readonly XmlQualifiedName DurationTypeName = new XmlQualifiedName("duration", Namespace);

      /// <summary>
      ///   The XML type name for a <see cref="Period"/>.
      /// </summary>
      public static readonly XmlQualifiedName PeriodTypeName = new XmlQualifiedName("period", Namespace);

      /// <summary>
      ///   The XML type name for a <see cref="Offset"/>.
      /// </summary>
      public static readonly XmlQualifiedName OffsetTypeName = new XmlQualifiedName("offset", Namespace);

      /// <summary>
      ///   The XML type name for a <see cref="OffsetDateTime"/>.
      /// </summary>
      public static readonly XmlQualifiedName OffsetDateTimeTypeName = new XmlQualifiedName("offsetDateTime", Namespace);

      /// <summary>
      ///   The XML type name for a <see cref="ZonedDateTime"/>.
      /// </summary>
      public static readonly XmlQualifiedName ZonedDateTimeTypeName = new XmlQualifiedName("zonedDateTime", Namespace);
      
      /// <summary>
      ///   The XML type name for a <see cref="RecurrenceRule"/>.
      /// </summary>
      public static readonly XmlQualifiedName RecurrenceRuleTypeName = new XmlQualifiedName("recurrenceRule", Namespace);

       
     /// <summary>
      ///   A cached copy of the XML schema for NodaTime.
      /// </summary>
      static XmlSchema schema;

      /// <summary>
      ///   Gets the <see cref="XmlSchema"/> for NodaTime;
      /// </summary>
      /// <remarks>
      ///   The schema is cached, so that multiple calls will have minimum overhead.
      /// <para>
      ///   The schema is defined in a resource of NodaTime assembly.  At some point, it should be publically available on the Internet. 
      ///   Currently you can find it at <see href="http://code.google.com/r/makaretu-noda-time-xml/source/browse/src/NodaTime/Xml/NodaTime.xsd"/>.
      /// </para>
      /// </remarks>
      public static XmlSchema Schema
      {
         get
         {
            if (schema == null)
            {
               lock (typeof(NodaTimeSchema))
               {
                  if (schema == null)
                  {
                     var assembly = Assembly.GetExecutingAssembly();
                     using (var stream = assembly.GetManifestResourceStream("NodaTime.Xml.NodaTime.xsd"))
                     using (var reader = XmlReader.Create(stream))
                     {
                        schema = XmlSchema.Read(reader, null);
                        schema.Namespaces.Add("noda", Namespace);
                     }
                  }
               }
            }

            return schema;
         }
      }

   }

}